<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<title>Google Maps Trip Demo</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>

<style type="text/css">
<!--

  .work_container {
  }

  .undo_controls {
	  padding:10px;
  }

  .form_element  {
	  padding:10px;
  }

  .label {
	  width:300px;
  }

  .report {
	  width: 617px;
	  height:100px;
	  background-color:#F0F0F0;
	  border: 1px solid #A0A0A0;
  }

 .header {
	 white-space: nowrap;
	 margin-left: 50px;
	 color: #0A0A0A;
 }

 .subheader {
   margin-left: 10px;
	 font-size: 14px;
	 font-weight: normal;
	 color: #0A0A0A;
	 width: 730px;
 }

 .comments {
	 font-style:italic;
	 font-size:14px;
	 color: #0F0F0F;
	 margin-left: 50px;
 }

.copyrigth {
	padding-top:20px;
	font-size:14px;
	color: #30304f;
	margin-left: 20px;
	width:730px;
}

.statusOn {
	border:1px solid red;
	background-color: lightblue;
}

.statusOff
{
	border:1px solid blue;
	background-color: white;
}
-->
</style>

<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=abcdefg" type="text/javascript"></script>
<script src="script/_compressed_jsoner.commons.js"></script>
<script src="script/_compressed_jsoner.js"></script>
<script src="script/_compressed_jsoner.serializer.js"></script>

<script src="script/jsoner.undomanager.js"></script>
<script src="script/jsoner.updater.js"></script>

<script language="javascript">

  var undoManager, serializer, updater;
  var undoProcessed = false, lockMap = false;
  var map;
  var markers = {};
  var output, undoMonitor, redoMonitor;
  var txt = '{"type":"UndoManager","data": {fMaxSize:32,fUndoData:[{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:45.706179285330855,$l:-83.408203125,x:-83.408203125,y:45.706179285330855}}],fUndoParams:[{"type":"GLatLng","data": {Zl:38.27268853598097,$l:-99.4921875,x:-99.4921875,y:38.27268853598097}}]}}},{action:{"type":"UndoableAction","data": {fStatus:1,fDoMethod:addMarker,fUndoMethod:removeMarker,fDoParams:[{"type":"GLatLng","data": {Zl:42.16340342422401,$l:-83.056640625,x:-83.056640625,y:42.16340342422401}}],fUndoParams:[{"type":"GLatLng","data": {Zl:42.16340342422401,$l:-83.056640625,x:-83.056640625,y:42.16340342422401}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:45.089035564831036,$l:-36.5625,x:-36.5625,y:45.089035564831036}}],fUndoParams:[{"type":"GLatLng","data": {Zl:45.706179285330855,$l:-83.408203125,x:-83.408203125,y:45.706179285330855}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:45.089035564831036,$l:-4.21875,x:-4.21875,y:45.089035564831036}}],fUndoParams:[{"type":"GLatLng","data": {Zl:45.089035564831036,$l:-36.5625,x:-36.5625,y:45.089035564831036}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:46.07323062540835,$l:16.875,x:16.875,y:46.07323062540835}}],fUndoParams:[{"type":"GLatLng","data": {Zl:45.089035564831036,$l:-4.21875,x:-4.21875,y:45.089035564831036}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:48.63290858589534,$l:32.080078125,x:32.080078125,y:48.63290858589534}}],fUndoParams:[{"type":"GLatLng","data": {Zl:46.07323062540835,$l:16.962890625,x:16.962890625,y:46.07323062540835}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:48.63290858589534,$l:32.080078125,x:32.080078125,y:48.63290858589534}},6],fUndoParams:[{"type":"GLatLng","data": {Zl:48.63290858589534,$l:32.080078125,x:32.080078125,y:48.63290858589534}},4]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.035973672195496,$l:36.1669921875,x:36.1669921875,y:50.035973672195496}}],fUndoParams:[{"type":"GLatLng","data": {Zl:48.63290858589534,$l:32.10205078125,x:32.10205078125,y:48.63290858589534}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.035973672195496,$l:36.1669921875,x:36.1669921875,y:50.035973672195496}},8],fUndoParams:[{"type":"GLatLng","data": {Zl:50.035973672195496,$l:36.1669921875,x:36.1669921875,y:50.035973672195496}},6]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.00067775723633,$l:36.1669921875,x:36.1669921875,y:50.00067775723633}}],fUndoParams:[{"type":"GLatLng","data": {Zl:50.032445247495104,$l:36.1669921875,x:36.1669921875,y:50.032445247495104}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.00067775723633,$l:36.1669921875,x:36.1669921875,y:50.00067775723633}},11],fUndoParams:[{"type":"GLatLng","data": {Zl:50.00067775723633,$l:36.1669921875,x:36.1669921875,y:50.00067775723633}},8]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:49.99891228081066,$l:36.2603759765625,x:36.2603759765625,y:49.99891228081066}}],fUndoParams:[{"type":"GLatLng","data": {Zl:50.00067775723633,$l:36.168365478515625,x:36.168365478515625,y:50.00067775723633}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.03288631476151,$l:36.24664306640625,x:36.24664306640625,y:50.03288631476151}}],fUndoParams:[{"type":"GLatLng","data": {Zl:49.99935365599503,$l:36.2603759765625,x:36.2603759765625,y:49.99935365599503}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.03288631476151,$l:36.24664306640625,x:36.24664306640625,y:50.03288631476151}},14],fUndoParams:[{"type":"GLatLng","data": {Zl:50.03288631476151,$l:36.24664306640625,x:36.24664306640625,y:50.03288631476151}},11]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.03150796610292,$l:36.255226135253906,x:36.255226135253906,y:50.03150796610292}}],fUndoParams:[{"type":"GLatLng","data": {Zl:50.03288631476151,$l:36.24672889709473,x:36.24672889709473,y:50.03288631476151}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.03150796610292,$l:36.255226135253906,x:36.255226135253906,y:50.03150796610292}},16],fUndoParams:[{"type":"GLatLng","data": {Zl:50.03150796610292,$l:36.255226135253906,x:36.255226135253906,y:50.03150796610292}},14]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.03240389723117,$l:36.255226135253906,x:36.255226135253906,y:50.03240389723117}}],fUndoParams:[{"type":"GLatLng","data": {Zl:50.031521749785334,$l:36.255226135253906,x:36.255226135253906,y:50.031521749785334}}]}}},{action:{"type":"UndoableAction","data": {fStatus:1,fDoMethod:addMarker,fUndoMethod:removeMarker,fDoParams:[{"type":"GLatLng","data": {Zl:50.03146661503191,$l:36.254539489746094,x:36.254539489746094,y:50.03146661503191}}],fUndoParams:[{"type":"GLatLng","data": {Zl:50.03146661503191,$l:36.254539489746094,x:36.254539489746094,y:50.03146661503191}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.04655739071663,$l:36.265525817871094,x:36.265525817871094,y:50.04655739071663}},12],fUndoParams:[{"type":"GLatLng","data": {Zl:50.04655739071663,$l:36.265525817871094,x:36.265525817871094,y:50.04655739071663}},16]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:50.27178780378988,$l:36.4306640625,x:36.4306640625,y:50.27178780378988}},8],fUndoParams:[{"type":"GLatLng","data": {Zl:50.27178780378988,$l:36.4306640625,x:36.4306640625,y:50.27178780378988}},12]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:53.69670647530323,$l:39.0234375,x:39.0234375,y:53.69670647530323}},4],fUndoParams:[{"type":"GLatLng","data": {Zl:53.69670647530323,$l:39.0234375,x:39.0234375,y:53.69670647530323}},8]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:52.53627304145948,$l:22.763671875,x:22.763671875,y:52.53627304145948}}],fUndoParams:[{"type":"GLatLng","data": {Zl:53.64463782485651,$l:39.0234375,x:39.0234375,y:53.64463782485651}}]}}},{action:{"type":"UndoableAction","data": {fDoMethod:moveMap,fUndoMethod:moveMap,fDoParams:[{"type":"GLatLng","data": {Zl:54.97761367069625,$l:9.31640625,x:9.31640625,y:54.97761367069625}},3],fUndoParams:[{"type":"GLatLng","data": {Zl:54.97761367069625,$l:9.31640625,x:9.31640625,y:54.97761367069625}},4]}}}]}};';

	function undo()
	{
		if (undoManager.isUndoFound() && !undoProcessed && map.isLoaded() )
		{
			undoProcessed = true;
			undoManager.callUndo();
			window.setTimeout( function ()
			{
				undoProcessed = false;
			}, 500 );
		}
	}

	function redo()
	{
		if (undoManager.isRedoFound() && !undoProcessed && map.isLoaded())
		{
			undoProcessed = true;
			undoManager.callRedo();
			window.setTimeout( function ()
			{
				undoProcessed = false;
			}, 500 );
		}
	}

    function undoShow()
	{
		var id = undefined;
		var time = 2500;

		function autoUndo()
		{
			if (id !== undefined)
			{
				window.clearTimeout(id);
				id = undefined;
			}
			if (undoManager.isRedoFound() )
			{
				id = window.setTimeout(function()
				{
					if ( map.isLoaded() )
					{
						undoManager.callRedo();
					}	
					autoUndo();
				}, time);
			}
			else
			{
				undoProcessed = false;
				lockMap = false;
			}
		}

		undoManager = serializer.deserialize(txt);
		lockMap = true;
		undoProcessed = true;
		map.clearOverlays();
		while( undoManager.isUndoFound() )
		{
		   undoManager.getRedoStack().push( undoManager.getUndoStack().pop() );
		}
		autoUndo();
	}
				  
	function doInit()
	{
		for ( var i = 0; i < document.forms.length; i++)
		{
			document.forms[i].reset();
		}

		undoManager = new UndoManager(16);
		serializer = new Serializer(true);
		
		updater = new Updater(100);
		updater.start();

		if (GBrowserIsCompatible())
		{
			map = new GMap2(document.getElementById("map"));
			var img1 = new Image();
			img1.src = "http://www.google.com/intl/ru_ALL/mapfiles/iw1.png";
			var img2 = new Image();
			img2.src = "http://www.google.com/intl/ru_ALL/mapfiles/iws2.png";


			map.addControl(new GLargeMapControl());
			map.addControl(new GOverviewMapControl());
			map.setCenter(new GLatLng(38.2726, -99.58), 4, G_HYBRID_MAP);

			var oldCenter;
			GEvent.addListener(map, "movestart", function()
			{
				oldCenter = map.getCenter();
			});
			GEvent.addListener(map, "moveend", function()
			{
				if (!undoProcessed && !lockMap && oldCenter !== undefined)
				{
					var center = map.getCenter();
					var action = new UndoableAction(moveMap, moveMap, center, oldCenter);
					undoManager.addAction(action);
					oldCenter = undefined;
				}
				lockMap = false;
			});

			GEvent.addListener(map, "zoomend", function(oldLevel, newLevel)
			{
				if (!undoProcessed && !lockMap && oldLevel !== undefined)
				{
					var center = map.getCenter();
					var action = new UndoableAction(moveMap, moveMap, [center, newLevel], [center, oldLevel]);
					undoManager.addAction(action);
					oldCenter = undefined;
				}
				lockMap = false;
			});

			GEvent.addListener(map, "click", function(overlay, point)
			{
				if (overlay !== null)
				{
					point = overlay.getPoint();
					var action = new UndoableAction(removeMarker, addMarker, [point], [point]);
					undoManager.callDo(action);
				}
				else
				{
					var action = new UndoableAction(addMarker, removeMarker, [point], [point]);
					undoManager.callDo(action);
				}
			});
		}

		updater.addAction("checkUNDO", null, function()
		{
			undoMonitor.value = undoManager.fUndoData.length;
			redoMonitor.value = undoManager.fRedoData.length;
			
			return undoManager.isUndoFound();
		}, ["undoCommand", "undoStatus"]);

		updater.addAction("checkREDO", null, function()
		{
			return undoManager.isRedoFound();
		}, ["redoCommand","redoStatus"]);

		updater.addAction("checkDeserialize", null, function()
		{
			return output.value.length > 1;
		}, "deserializeCommand");

		updater.switchAction("checkUNDO", "checkREDO",  "checkDeserialize", true);

		updater.addAction("callUndo", function()
		{
			undo();
		}, null, null, "Alt-U");

		updater.addAction("callRedo", function()
		{
			redo();
		}, null, null, "Alt-R");
		updater.switchAction("callUndo", "callRedo", true);

        output = document.getElementById("report");
		undoMonitor = document.getElementById("undoStatus");
		redoMonitor = document.getElementById("redoStatus");

		document.getElementById("show").removeAttribute("disabled");
	}

	function moveMap(aCenter, aZoom)
	{
    lockMap = true;
		if ( aCenter !== undefined )
		{
			map.panTo(aCenter);
		}
		if ( aZoom !== undefined )
		{
			map.setZoom(aZoom);
		}
	}

  function removeMarker(aPoint)
  {
	  var marker = markers[aPoint];
	  if (marker !== undefined)
	  {
		  map.closeInfoWindow();
		  markers[aPoint] = undefined;
		  map.removeOverlay(marker);
	  }
  }

  function addMarker(aPoint)
  {
	  var marker = new GMarker(aPoint);
    map.addOverlay(marker);

	  if ( (aPoint.x > -83.057 && aPoint.x < -83.055) && (aPoint.y > 42.162 && aPoint.y < 42.164) )
	  {
		  marker.openInfoWindowHtml("They've created <b>Google Maps</b><br>"+
		                            "Google Inc,<br>"+
                                "<a href='http://maps.google.com/' target='_blank'>http://maps.google.com/</a>"
		  );
	  }
	  else
	  if ( (aPoint.x > 36.24 && aPoint.x < 36.26) && (aPoint.y > 50.028 && aPoint.y < 50.032) )
	  {
		  marker.openInfoWindowHtml("Ukraine, Kharkov <br>"+
		                            "SoftAMIS <b><a href='http://www.soft-amis.com' target='_blank'>www.soft-amis.com</a><br>This demo was created there.");
	  }
	  markers[aPoint] = marker;
	  return marker;
  }

  function onChangeBox(aBox)
	{
		document.getElementById('hv').style.visibility = aBox.checked ? 'visible': 'hidden'
	}

  function serializeManager()
  {
	  output.value = serializer.serialize(undoManager);
  }

  function deserializeManager()
  {
	undoManager = serializer.deserialize(output.value);
  }

  function init()
  {
    window.setTimeout( doInit, 1000 );
  }
</script>

</head>

<body onload="init()">
  <h1 class="header">
	   Make Google Maps Trip.
  </h1><hr>
  <div class="subheader">
	  Main purpose of this example to show possibility of creation of
	  persistent JavaScript objects on client's side unsing Undo Manager as an example.
    Additionaly it demonstrates updatable action pattern to make
	  loosely coupled action based architecture.
	</div>

  <div class="work_container">
    <div id="map" style="margin:30px; width: 650px; height: 300px"></div>

	  <div class="undo_controls">
		  <form name="demoControls" action="#">
			  <div class="form_element">
			     <textarea id="report" readonly class="report" wrap="off"></textarea>
			  </div>
			  <div class="form_element">
					<input type="button" disabled id="undoCommand" value="UNDO"  onclick="undo()">
					<input type="button" disabled id="redoCommand" value="REDO" onclick="redo()">
					<input type="button" disabled id="show" value="Start Google Maps trip" onclick="undoShow()">

				  <span class="label">Manager status:</span>
				  <input type="text" class="statusOff" readonly size="3" id="undoStatus">
				  <input type="text" class="statusOff" readonly size="3" id="redoStatus">
				</div>
			  <div class="form_element">
					<input type="button" id="serializeCommand" value="Serialize Manager" onclick="serializeManager()">
					<input type="button" disabled id="deserializeCommand" value="Deserialize Manager" onclick="deserializeManager()">
				</div>

		  </form>
	 </div>
  </div>

  <div class="footer">
	  <div class="comments" >
	    <div>Press <b>Alt-U</b> to call undo operation.</div>
		  <div>Press <b>Alt-R</b> to call redo operation.</div>
	  </div>
	  <div class="copyrigth">
			<div>
				JSONER can be downloaded free from <a href="http://sourceforge.net/projects/jsontools">http://sourceforge.net/projects/jsontools</a>.
			</div>
	  </div>
 </div>  
</body>
</html>
